/* 
 * File:   OperacionSincronizacionArchivosNuevos.cpp
 * Author: maximiliano
 * 
 * Created on 15 de junio de 2013, 10:41
 */

#include "client_OperacionSincronizacionArchivosNuevos.h"
#include "client_OperacionCargaArchivo.h"
#include "client_OperacionDescargaArchivo.h"
#include "common_TokenFactory.h"

using namespace TP::Comunicacion;
using namespace TP::Operaciones;

OperacionSincronizacionArchivosNuevos::OperacionSincronizacionArchivosNuevos(const uint32_t &pToken, Repositorio **pRepositorioLocal, Repositorio **pRepositorioServidor, FileServiceProxy* pFileService) : OperacionSecuencial(pToken) {
    _repositorioLocal = pRepositorioLocal;
    _repositorioServidor = pRepositorioServidor;
    _fileService = pFileService;
    this->setFinalizada(true);
}

OperacionSincronizacionArchivosNuevos::~OperacionSincronizacionArchivosNuevos() {}

void OperacionSincronizacionArchivosNuevos::ejecutar(){
    
    /* Se calcula el esquema de trabajo.  Esto es, las operaciones que tiene que
     * ejecutar el secuencia la operacion de sincronizacion a fin de llevar
     * a cabo de forma satisfactoria la sincronizacion de repositorios.
     */
    this->CalcularEsquemaTrabajo();
    
    /* Se ejecuta el proceso de trabajo.
     */
    OperacionSecuencial::ejecutar();
    
}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajo(){
    
    this->CalcularEsquemaTrabajoArchivosNuevosEnCliente();
    
    // this->CalcularEsquemaTrabajoArchivosNuevosEnServidor();
}

SetRepoItem OperacionSincronizacionArchivosNuevos::getArchivosNuevosServidor(){
    
    SetRepoItem items;
    
    SetRepoItemIterator itRepoServer = (*_repositorioServidor)->GetItemIterator();
    
    while (itRepoServer < (*_repositorioServidor)->GetItemIteratorEnd())
    {
        RepoItem* itemLocal = (*_repositorioLocal)->GetRepoItemByFilename((*itRepoServer)->GetFilename());
        if (NULL == itemLocal)
        {
            items.push_back(itemLocal);
        }
        itRepoServer++;
    }
    
    return items;
}

SetRepoItem OperacionSincronizacionArchivosNuevos::getArchivosNuevosLocales(){
    
    SetRepoItem items;
    SetRepoItemIterator itRepoLocal = (*_repositorioLocal)->GetItemIterator();
    
    while (itRepoLocal < (*_repositorioLocal)->GetItemIteratorEnd())
    {
        if (ARCHIVO_A_PUBLICAR == (*itRepoLocal)->GetEstado())
        {
            items.push_back(*itRepoLocal);
        }
        itRepoLocal++;
    }
    
    return items;
}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajoArchivosNuevosEnServidor(){
 
    // Configura el esquema de trabajo de descarga de archivos nuevos desde el servidor.
    
    SetRepoItem archivosNuevosServidor = this->getArchivosNuevosServidor();
    SetRepoItemIterator itRepoServer = archivosNuevosServidor.begin();
    while (itRepoServer < archivosNuevosServidor.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionDescargaArchivo 
                (
                  TokenFactory::Crear()
                , _fileService
                , (*_repositorioLocal)
                , (*itRepoServer)->GetFilename()
                , (*itRepoServer)->GetVersion()
                )
        );
        
        itRepoServer++;
    }
    archivosNuevosServidor.clear();

}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajoArchivosNuevosEnCliente(){
 
    // Configura el esquema de trabajo de carga de archivos desde el cliente.
    
    vector<RepoItem*> archivosNuevosLocales = this->getArchivosNuevosLocales();
    vector<RepoItem*>::iterator itRepoLocal = archivosNuevosLocales.begin();
    
    while (itRepoLocal < archivosNuevosLocales.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionCargaArchivo 
            (
              TokenFactory::Crear()
            , _fileService
            , (*_repositorioLocal)
            , (*itRepoLocal)->GetFilename()
            )
        );
        
        itRepoLocal++;
    }
    
    archivosNuevosLocales.clear();
}